/**
 * @file mf_fifo.h
 * @author Mayfly Zhang (zhangquzhi123456@163.com)
 * @brief 声明操作FIFO的函数。支持结构化数据单元
 * @version 0.0
 * @date 2021-03-29
 *
 * @copyright Copyright (c) 2021
 *
 */

#ifndef _MF_FIFO_H_
#define _MF_FIFO_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include "typedef.h"

/**
 * @brief   定义FIFO类型
 *
 */
typedef struct
{
    void *data;          /*!< 指向数据Buffer */
    u16  head;           /*!< 队列头，指向下一个待取数据 */
    u16  tail;           /*!< 队列尾，指向下一个待写数据 */

    u16  unit;           /*!< 每个Buffer成员大小 */
    u16  size;           /*!< 数据Buffer的成员数目 */
    u16  len;            /*!< 有效数据的长度 */
} FIFO_t;

/**
 * @brief   定义判断FIFO是否为FULL、EMPTY、EXIST的操作
 *
 */
#define FIFO_IS_FULL(fifo)         (((fifo)->len >= (fifo)->size)   ? 1U : 0U)
#define FIFO_IS_EMPTY(fifo)        (((fifo)->len == 0U)             ? 1U : 0U)
#define FIFO_IS_EXIST(fifo)        (((fifo)->data != MF_NULL)       ? 1U : 0U)

/**
 * @brief   获取FIFO的head
 *
 * @param fifo     指向FIFO的指针
 * @return u16      FIFO的head
 */
static inline u16 fifo_head(FIFO_t *fifo)
{
    return fifo->head;
}

/**
 * @brief   获取FIFO的tail
 *
 * @param fifo     指向FIFO的指针
 * @return u16      FIFO的tail
 */
static inline u16 fifo_tail(FIFO_t *fifo)
{
    return fifo->tail;
}

/**
 * @brief   获取FIFO的unit
 *
 * @param fifo     指向FIFO的指针
 * @return u16      FIFO的unit
 */
static inline u16 fifo_unit(FIFO_t *fifo)
{
    return fifo->unit;
}

/**
 * @brief   获取FIFO的size
 *
 * @param fifo     指向FIFO的指针
 * @return u16      FIFO的size
 */
static inline u16 fifo_size(FIFO_t *fifo)
{
    return fifo->size;
}

/**
 * @brief   获取FIFO的total size
 *
 * @param fifo     指向FIFO的指针
 * @return u16      FIFO的total size
 */
static inline u32 fifo_total_size(FIFO_t *fifo)
{
    return (fifo->size * fifo->unit);
}

/**
 * @brief   获取FIFO的len
 *
 * @param fifo     指向FIFO的指针
 * @return u16      FIFO的len
 */
static inline u16 fifo_len(FIFO_t *fifo)
{
    return fifo->len;
}

/**
 * @brief   获取FIFO数据Buffer
 *
 * @param fifo     指向FIFO的指针
 * @return void *   FIFO的Buffer
 */
static inline void * fifo_data(FIFO_t *fifo)
{
    if (!FIFO_IS_EXIST(fifo))
        return MF_NULL;

    return fifo->data;
}

/**
 * @brief   获取FIFO的tail成员
 *
 * @param fifo     指向FIFO的指针
 * @return void *   FIFO的尾部
 */
static inline void * fifo_member_tail(FIFO_t *fifo)
{
    if (!FIFO_IS_EXIST(fifo))
        return MF_NULL;
    if (FIFO_IS_FULL(fifo))
        return MF_NULL;

    return ((u8 *)fifo->data + fifo->tail*fifo->unit);
}

/**
 * @brief   获取FIFO的head成员
 *
 * @param fifo     指向FIFO的指针
 * @return void *   FIFO的头部
 */
static inline void * fifo_member_head(FIFO_t *fifo)
{
    if (!FIFO_IS_EXIST(fifo))
        return MF_NULL;
    if (FIFO_IS_EMPTY(fifo))
        return MF_NULL;

    return ((u8 *)fifo->data + fifo->head*fifo->unit);
}

/**
 * @brief   FIFO数据增加
 *
 * @param fifo     指向FIFO的指针
 */
static inline void fifo_increase(FIFO_t *fifo)
{
    if (!FIFO_IS_FULL(fifo))
    {
        fifo->len++;
        fifo->tail++;
        if (fifo->tail == fifo->size)
           fifo->tail = 0U;
    }
}

/**
 * @brief   FIFO数据减少
 *
 * @param fifo     指向FIFO的指针
 */
static inline void fifo_decrease(FIFO_t *fifo)
{
    if (!FIFO_IS_EMPTY(fifo))
    {
        fifo->len--;
        fifo->head++;
        if (fifo->head == fifo->size)
           fifo->head = 0U;
    }
}

/**
 * @brief   声明FIFO函数
 *
 */
u8 fifo_init(FIFO_t *fifo, void * const data, u16 unit, u16 size);
u8 fifo_write(FIFO_t *fifo, void const * const data);
void * fifo_read(FIFO_t *fifo);
u8 fifo_delete(FIFO_t *fifo);

#ifdef __cplusplus
}
#endif

#endif
